/**
 * Copyright (c) 2018-2023, NXOS Development Team
 * SPDX-License-Identifier: Apache-2.0
 *
 * Contains:
 *
 * Change Logs:
 * Date           Author            Notes
 * 2023-08-30     Shiroko           Init
 */
#ifndef __DRIVERS_VIRTIO_DEVICES_VIRTIO_CONSOLE_H__
#define __DRIVERS_VIRTIO_DEVICES_VIRTIO_CONSOLE_H__

// Queues
#define VIRTIO_CONSOLE_QUEUE_RECEIVE_N(N)       (2*(N) + ((N) != 0 ? 2 : 0))     // N starts from 0
#define VIRTIO_CONSOLE_QUEUE_TRANSMIT_N(N)      (2*(N) + ((N) != 0 ? 2 : 0) + 1)

#define VIRTIO_CONSOLE_QUEUE_RECEIVE_CONTROL    2
#define VIRTIO_CONSOLE_QUEUE_TRANSMIT_CONTROL   3
#define VIRTIO_CONSOLE_QUEUE_RECEIVE            VIRTIO_CONSOLE_QUEUE_RECEIVE_N(0)
#define VIRTIO_CONSOLE_QUEUE_TRANSMIT           VIRTIO_CONSOLE_QUEUE_TRANSMIT_N(0)

// Features
// Configuration cols and rows are valid.
#define VIRTIO_CONSOLE_FEATURE_SIZE         (1<<0)
// Device has support for multiple ports; max_nr_ports is valid and control virtqueues will be used.
#define VIRTIO_CONSOLE_FEATURE_MULTIPORT    (1<<1)
// Device has support for emergency write. Configuration field emerg_wr is valid.
#define VIRTIO_CONSOLE_FEATURE_EMERG_WRITE  (1<<2)

// Event
// Sent by the driver at initialization to indicate that it is ready to receive control messages. A value of 1 indicates success, and 0 indicates failure. The port number id is unused.
#define VIRTIO_CONSOLE_DEVICE_READY     (0)
// Sent by the device, to create a new port. value is unused.
#define VIRTIO_CONSOLE_DEVICE_ADD       (1)
// Sent by the device, to remove an existing port. value is unused.
#define VIRTIO_CONSOLE_DEVICE_REMOVE    (2)
// Sent by the driver in response to the device’s VIRTIO_CONSOLE_PORT_ADD message, to indicate that the port is ready to be used. A value of 1 indicates success, and 0 indicates failure.
#define VIRTIO_CONSOLE_PORT_READY       (3)
// Sent by the device to nominate a port as a console port. There MAY be more than one console port.
#define VIRTIO_CONSOLE_CONSOLE_PORT     (4)
// Sent by the device to indicate a console size change. value is unused. The buffer is followed by the number of columns and rows:
#define VIRTIO_CONSOLE_RESIZE           (5)
// This message is sent by both the device and the driver. value indicates the state: 0 (port closed) or 1 (port open). This allows for ports to be used directly by guest and host processes to communicate in an application-defined manner.
#define VIRTIO_CONSOLE_PORT_OPEN        (6)
// Sent by the device to give a tag to the port. This control command is immediately followed by the UTF-8 name of the port for identification within the guest (without a NUL terminator).
#define VIRTIO_CONSOLE_PORT_NAME        (7)

struct VirtioConsoleControl
{
    NX_U32 id; // port
    NX_U16 event;
    NX_U16 value;
};
typedef struct VirtioConsoleControl VirtioConsoleControl;


struct VirtioConsoleDeviceConfig
{
    NX_U16 cols;        // Only if FEATURE_SIZE is set
    NX_U16 rows;        // Only if FEATURE_SIZE is set
    NX_U32 max_ports;   // Only if FEATURE_MULTIPORT is set
    NX_U32 emerg_wr;    // Only if FEATURE_EMERG_WRITE is set
};
typedef struct VirtioConsoleDeviceConfig VirtioConsoleDeviceConfig;

#define VIRTIO_CONSOLE_RECEIVE_BUF_SIZE 16

struct VirtioConsoleDeviceExtension
{
    VirtioConsoleDeviceConfig *deviceConfig;
    NX_Fifo **receiveQueues;
    char **receiveBuffers;
    int selectedPort;
    VirtioConsoleControl *receiveControlBuffer;
};
typedef struct VirtioConsoleDeviceExtension VirtioConsoleDeviceExtension;

#endif // __DRIVERS_VIRTIO_DEVICES_VIRTIO_CONSOLE_H__

